package com.handinglian.ai.netty.client;

import com.alibaba.fastjson.JSONObject;
import com.handinglian.ai.netty.request.AuthReqPacket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class NettyClient {
    private EventLoopGroup group = new NioEventLoopGroup();
    @Value("${netty.port}")
    private int port;
    @Value("${netty.host}")
    private String host;
    @Value("${netty.enable}")
    private boolean enable;

    private Channel channel;

    public void sendMsg(Object packet) {
        String message = JSONObject.toJSONString(packet);
        String head = "<<<length=" + getWordCountCode(message, "UTF-8") + ">>>";
        message = head + message;
        System.out.println("send="+message);
        channel.writeAndFlush(message);
    }

    public void sendMsgClose(Object packet) {
        String message = JSONObject.toJSONString(packet);
        String head = "<<<length=" + getWordCountCode(message, "UTF-8") + ">>>";
        message = head + message;
        System.out.println("send="+message);
        channel.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    }

    /**
     * 按特定的编码格式获取长度
     */
    public int getWordCountCode(String str, String code){
        int tmp=0;
        try {
            tmp=str.getBytes(code).length;
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(),e);
        }
        return tmp;
    }

    @PostConstruct
    public void start()  {
        if (!enable){
            return;
        }
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .remoteAddress(host, port)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new NettyClientInitializer());

        ChannelFuture future = bootstrap.connect();
        //客户端断线重连逻辑
        future.addListener((ChannelFutureListener) future1 -> {
            if (future1.isSuccess()) {
                log.info("连接Netty服务端成功");
                channel = future1.channel();
                AuthReqPacket authReqPacket = new AuthReqPacket();
                AuthReqPacket.AuthBean authBean = new AuthReqPacket.AuthBean();
                authBean.setUser("robot");
                authBean.setPwd("12345");
                authReqPacket.setAuth(authBean);
                sendMsg(authReqPacket);
            } else {
                log.info("连接失败，进行断线重连");
                future1.channel().eventLoop().schedule(() -> start(), 20, TimeUnit.SECONDS);
            }
        });
    }
}
